package com.sd365.permission.centre.service.impl;/*
 * @Auther:hantianbing
 * @Date:2022/12/7
 * @Description:RoleService实现类
 */

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sd365.common.core.annotation.stuffer.IdGenerator;
import com.sd365.common.core.common.aop.MyPageInfo;
import com.sd365.common.core.common.exception.BusinessException;
import com.sd365.common.core.context.BaseContextHolder;
import com.sd365.common.util.BeanUtil;
import com.sd365.common.util.StringUtil;
import com.sd365.permission.centre.dao.mapper.*;
import com.sd365.permission.centre.entity.*;
import com.sd365.permission.centre.pojo.dto.*;
import com.sd365.permission.centre.pojo.query.RoleQuery;
import com.sd365.permission.centre.pojo.query.UserQuery;
import com.sd365.permission.centre.pojo.vo.*;
import com.sd365.permission.centre.service.RoleService;
import com.sd365.permission.centre.service.exception.UserCentreExceptionCode;
import com.sd365.permission.centre.service.util.UserRoleResourceUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName RoleServiceImpl
 * @Description
 * @Author hantianbing
 * @Date 2022/12/7 20:14
 **/
@Service
@Slf4j
public class RoleServiceImpl extends AbstractBaseDataServiceImpl implements RoleService {
    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private IdGenerator idGenerator;

    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private OrganizationMapper organizationMapper;

    @Autowired
    private RoleCompanyMapper roleCompanyMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleResourceMapper roleResourceMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private DepartmentMapper departmentMapper;


    @Override
    public Boolean initRoleResourceRedis(Role role) {
        return null;
    }

    @Override
    public Boolean assignResource(RoleResourceDTO roleResourceDTO) {
        //非空判断
        if(roleResourceDTO == null){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_RESOURCE_DTO_NULL, new Exception("角色用户DTO为空"));
        }
        //获取所有角色
        List<Long> roleIds = UserRoleResourceUtils.getRoleIdsFromRoleResource(roleResourceDTO);
        if(roleIds==null || roleIds.size()==0){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_ID_NULL,new Exception("传入的角色id是空的"));
        }
        //把每个角色的资源信息进行清空
        if (!deleteAllRoleResourceByRoleIds(roleIds)) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_RESOURCE_DELETE_FAIL, new Exception("角色资源删除失败"));
        }
        //获取所有资源, 如果资源不存在， 那么就是只做了清除， 没有添加。
        List<Long> resourceIds = UserRoleResourceUtils.getResourceIdsFromRoleResource(roleResourceDTO);
        if(resourceIds==null || resourceIds.size()==0){
            return true;
        }
        //构建roleResources
        List<RoleResource> roleResources = new ArrayList<>();
        for (Long roleId : roleIds) {
            for (Long resourceId : resourceIds) {
                RoleResource roleResource = getRoleResource(resourceId, roleId);
                roleResources.add(roleResource);
            }
        }
        //插入所有的RoleResources
        for (RoleResource roleResource : roleResources) {
            if(roleResourceMapper.insert(roleResource)<=0){
                throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_RESOURCE_INSERT_FAIL, new Exception("roleResource 插入失败"));
            }
        }
        //todo 后面改进一次性插入
//        if (roleResourceMapper.insertList(roleResources)<=0) {
//            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_RESOURCE_INSERT_FAIL, new Exception("roleResource 插入失败"));
//        }
        return true;
    }

    @Override
    public Boolean assignUser(UserRoleDTO userRoleDTO) {
        //获取数据
        List<Long> userIds = UserRoleResourceUtils.getUserIdsFromUserRoleDTO(userRoleDTO);
        List<Long> roleIds = UserRoleResourceUtils.getRoleIdsFromUserRoleDTO(userRoleDTO);
        //对每一个用户做处理
        for (Long userId : userIds) {
            //根据用户id获取角色id
            List<Long> roleIdsByUserId = getRoleIdsByUserId(userId);
            for (Long roleId : roleIds) {
                //判断空不空
                if( roleIdsByUserId != null && roleIdsByUserId.contains(roleId)){
                    continue;
                }
                //添加userRole
                if (!addUserRole(userId, roleId)) {
                    throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_RESOURCE_ADD_FAIL, new Exception("角色分配用户失败"));
                }
            }
        }
        return true;
    }

    @Override
    public List<Node> queryResourceByRoleId(long roleId) {
        return null;
    }

    @Override
    public List<Node> selectCompany() {
        ArrayList<Node> objects = new ArrayList<>();
        Node node = new Node();
        node.setId(1L);
        node.setName("123");
        objects.add(node);
        return objects;
    }

    @Override
    public Boolean add(RoleDTO roleDTO) {
        //是不是空的
        if(roleDTO == null){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_DTO_NULL, new Exception("roleDTO是空的"));
        }
        Role role = BeanUtil.copy(roleDTO, Role.class);
        //判断信息完整
        if(StringUtil.isEmpty(role.getRemark()) || StringUtil.isEmpty(role.getCode()) || StringUtil.isEmpty(role.getName())){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_MESSAGE_NULL, new Exception("信息不完整"));
        }
        setRoleProperties(role);
        if(role.getCompanyId() == null || role.getCompanyId() ==0){
            role.setCompanyId(roleDTO.getCompanyId());
            role.setOrgId(roleDTO.getOrgId());
            role.setTenantId(roleDTO.getTenantId());
        }
        //判断不能是重复的code
        List<String> strings = roleMapper.queryAllRoleCode();
        for (String string : strings) {
            if (role.getCode().equals(string)) {
                throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_CODE_REPEAT,new Exception("角色的code不能重复"));
            }
        }
        //插入
        return roleMapper.insert(role) >0;
    }


    @Override
    public Boolean remove(Long id, Long version) {
        //角色id非空判断
        if(id==null){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_ID_NULL, new Exception("角色Id不能为空"));
        }
        //角色版本不能为空
        if(version == null){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_VERSION_NULL, new Exception("角色的版本不能为空"));
        }
        //角色id必须存在
        if(roleMapper.selectById(id)==null){
            return false;
        }

        //清除用户和角色的关联
        if (!deleteAllUserRoleByRoleId(id)) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_USER_ROLE_DELETE_FAIL, new Exception("用户角色删除失败"));
        }
        //清除角色和公司的资源的关联
        if (!deleteAllUserResourceByRoleId(id)) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_RESOURCE_DELETE_FAIL, new Exception("角色资源删除失败"));
        }
        //删除自己
        if (roleMapper.deleteByPrimaryKey(id) <=0) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_DELETE_FAIL,new Exception("角色删除失败"));
        }
        return true;
    }

    /***
     * @Description 通过角色id删除所有
     *
     * @Param
     * @return java.lang.Boolean
     * @Date 2022/12/16 13:56
     * @Author hantianbing
     **/
    private Boolean deleteAllUserResourceByRoleId(Long roleId){
        //如果表中没有数据就返回true
        List<RoleResource> roleResources = roleResourceMapper.selectResourceByRoleId(roleId);
        if (roleResources == null || roleResources.size()==0) {
            return true;
        }
        if (roleResourceMapper.deleteByRoleId(roleId) <= 0) {
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_USER_MODULE_USER_ROLE_DELETE_FAIL, new Exception("角色删除失败"));
        } else {
            return true;
        }
    }



    @Override
    public RoleDTO modify(RoleDTO roleDTO) {
        //是不是空的
        if(roleDTO == null){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_DTO_NULL, new Exception("roleDTO是空的"));
        }
        //得到role
        Role role = BeanUtil.copy(roleDTO, Role.class);
        //判断角色信息是否完整
        if(role.getCode() == null || role.getName()==null){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_MESSAGE_NULL,new Exception("角色的名和code不能为空"));
        }
        //TODO 方法可能有些问题
        super.baseDataStuff4Add(role);
        //设置Version
        if (role.getVersion() != null) {
            Long version = role.getVersion();
            role.setVersion(version++);
        }
        //更新的code不能重复
        if(!roleMapper.selectByPrimaryKey(role.getId()).getCode().equals(role.getCode()) &&
                roleMapper.selectByCode(role.getCode()) != null){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_CODE_REPEAT, new Exception("角色code已经存在"));
        }
        //更新操作
        Example example = new Example(Resource.class);
        example.createCriteria().andEqualTo("id", role.getId());
        if(roleMapper.updateByExampleSelective(role, example) > 0){
            return BeanUtil.copy(roleMapper.selectById(role.getId()), RoleDTO.class);
        }else {
            return null;
        }
    }

    @Override
    public List<RoleVO> commonQuery(RoleQuery roleQuery) {
        //非空判断
        if(roleQuery == null){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_NULL, new Exception("roleQuery是空的"));
        }
        Role copy = BeanUtil.copy(roleQuery, Role.class);
        //分页
        PageHelper.startPage(roleQuery.getPageNum(), roleQuery.getPageSize());
        List<Role> roles = roleMapper.commonQuery(copy);
        //分页信息设置
        Page<Role> page = (Page<Role>) roles;
        BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));
        //封装Vo
        List<RoleVO> roleVos = BeanUtil.copyList(roles, RoleVO.class);
        //添加company、organizationDTO信息
        for (RoleVO roleVO : roleVos) {
            //通过各自的id查询出来信息
            Company company = companyMapper.selectById(roleVO.getCompanyId());
            Organization organization = organizationMapper.selectByPrimaryKey(roleVO.getOrgId());
            //放到Vo里面
            roleVO.setCompanyDTO(BeanUtil.copy(company, CompanyDTO.class));
            roleVO.setOrganizationDTO(BeanUtil.copy(organization, OrganizationDTO.class));
        }
        return roleVos;
    }

    @Override
    public RoleVO queryById(Long id) {
        Role role = roleMapper.selectById(id);
        if(role==null){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_NULL, new Exception("角色不能为空"));
        }
        RoleVO roleVO = BeanUtil.copy(role, RoleVO.class);
        return roleVO;
    }

    @Override
    public RoleDTO copy(Long id) {
        //查询id role
        Role role1 = roleMapper.selectById(id);
        //判空
        if(role1 == null){
            throw new BusinessException("", "没有匹配的角色");
        }
        //新建角色
        Role copy = new Role();
        //先拷贝所有属性，再重新赋值一些属性
        BeanUtil.copy(role1, copy);
        copy.setId(idGenerator.snowflakeId());
        copy.setVersion(0L);
        super.baseDataStuff4Add(copy);
        //插入
        int insert = roleMapper.insert(copy);
        if(insert>0){
            return BeanUtil.copy(copy, RoleDTO.class);
        }else{
            return null;
        }
    }

    @Override
    public Boolean batchRemove(RoleDTO[] roleDtos) {
        //循环遍历删除
        for (RoleDTO query : roleDtos) {
            if (!this.remove(query.getId(), query.getVersion())) {
                throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_DELETE_FAIL, new Exception("角色删除失败"));
            }
        }
        return true;
    }

    @Override
    public List<UserVO> commonQueryUser(UserQuery userQuery) {
        //todo 代码优化
        List<UserRole> userRoles = userRoleMapper.selectByRoleId(userQuery.getRoleId());
        List<Long> collect = userRoles.stream().map(UserRole::getUserId).collect(Collectors.toList());
        List<RoleVO> roleVos = new ArrayList<>();
        //分页查询用户
        PageHelper.startPage(userQuery.getPageNum(), userQuery.getPageSize());

        List<User> users = userMapper.commonQuery(userQuery);
        //分页信息设置
        Page<User> page = (Page<User>) users;
        BaseContextHolder.set("pageInfo", JSON.toJSONString(new MyPageInfo(page.getTotal(), page.getPages())));

        List<UserVO> userDtos = new ArrayList<>();
        for (User user : users) {
            UserVO userVO = BeanUtil.copy(user, UserVO.class);
            //如果包含角色，就加入
            if(collect.contains(user.getId())){
                userVO.setRoleList(roleVos);
            }
            //查询公司信息
            Company company = companyMapper.selectById(userVO.getCompanyId());
            if(company!=null){
                userVO.setCompanyVO(BeanUtil.copy(company, CompanyVO.class));
            }
            //查询部门信息
            Department department = departmentMapper.selectByPrimaryKey(userVO.getDepartmentId());
            if(department !=null){
                userVO.setDepartmentVO(BeanUtil.copy(department, DepartmentVO.class));
            }
            userDtos.add(userVO);
        }
        return userDtos;
    }

    @Override
    public RoleDTO queryUserResource(Long id) {
        return null;
    }

    @Override
    public RoleCompanyVO queryRoleCompanyById(Long id) {
        RoleCompanyVO roleCompanyVos = roleMapper.queryRoleCompanyById(id);
        return roleCompanyVos;
    }


    @Override
    public Boolean modifyRoleCompany(RoleCompanyDTO roleCompanyDTO) {
        //构建example， 删除全部roleId 匹配的role_company，然后在全部插入



        //插入全部的role和company记录
        //todo
        return true;
    }


    /**
     * 查看有没有这个角色
     * @param roleDTO
     * @return
     */
    @Override
    public boolean haveRole(RoleDTO roleDTO) {
        if(roleDTO == null){
            throw new BusinessException("", "传入的数据为空");
        }
        //code判空
        if(StringUtil.isEmpty(roleDTO.getCode())){
            throw new BusinessException("500", "角色编码不能是空的");
        }
        //角色code不存在
        Role role = roleMapper.selectByCode(roleDTO.getCode());
        if(role==null){
            return false;
        }
        Role copy = BeanUtil.copy(roleDTO, Role.class);
        return roleMapper.haveRole(copy) >0;
    }

    /***
     * @Description 设置角色信息
     *
     * @Param
     * @return com.sd365.permission.centre.entity.Role
     * @Date 2022/12/16 12:19
     * @Author hantianbing
     **/
    private Role setRoleProperties(Role role){
        //设置id
        role.setId(idGenerator.snowflakeId());
        //添加creat信息
        super.baseDataStuff4Add(role);
        super.baseDataStuffCommonPros(role);
        //设置status
        role.setVersion(INITIALIZE_VERSION_VALUE);
        role.setStatus(INITIALIZE_STATUS_VALUE);

        return role;
    }


    /***
     * @Description 根据角色id删除所有userRole
     *
     * @Param
     * @return java.lang.Boolean
     * @Date 2022/12/16 12:01
     * @Author hantianbing
     **/
    private Boolean deleteAllUserRoleByRoleId(Long id) {
        //如果表中没有数据就返回true
        List<UserRole> userRoles = userRoleMapper.selectByRoleId(id);
        if (userRoles == null || userRoles.size()==0) {
            return true;
        }
        if (userRoleMapper.deleteAllByRoleId(id) <= 0) {
            return false;
        } else {
            return true;
        }
    }

    /***
     * @Description 根据用角色的id删除所有roleResources
     *
     * @Param
     * @return java.lang.Boolean
     * @Date 2022/12/16 11:53
     * @Author hantianbing
     **/
    private Boolean deleteAllRoleResourceByRoleIds(List<Long> roleIds){
        if(roleIds==null){
            throw new BusinessException(UserCentreExceptionCode.BUSINESS_ROLE_MODULE_ROLE_ID_NULL, new Exception("角色Id为空"));
        }
        //构建example
        Example example = new Example(RoleResource.class);
        example.createCriteria().andIn("roleId", roleIds);
        //
        List<RoleResource> roleResources = roleResourceMapper.selectByExample(example);
        if (roleResources ==null || roleResources.size()==0 ) {
            return true;
        }
        int i = roleResourceMapper.deleteByExample(example);
        if(i<=0){
            return false;
        }else{
            return true;
        }
    }

    /***
     * @Description 添加UserRole
     *
     * @Param
     * @return java.lang.Boolean
     * @Date 2022/12/15 20:00
     * @Author hantianbing
     **/
    private Boolean addUserRole(Long userId, Long roleId){
        UserRole userRole = new UserRole();
        userRole.setVersion(1L);
        super.baseDataStuffCommonPros(userRole);
        super.baseDataStuff4Add(userRole);
        userRole.setId(idGenerator.snowflakeId());
        userRole.setUserId(userId);
        userRole.setRoleId(roleId);
        return userRoleMapper.insert(userRole)>0;
    }

    /***
     * @Description 添加角色用户
     *
     * @Param
     * @return java.lang.Boolean
     * @Date 2022/12/15 18:16
     * @Author hantianbing
     **/
    private RoleResource getRoleResource(Long resourceId, Long roleId){
        RoleResource roleResource = new RoleResource();
        //设置id
        roleResource.setId(idGenerator.snowflakeId());
        roleResource.setRoleId(roleId);
        roleResource.setResourceId(resourceId);
        //设置信息
        super.baseDataStuffCommonPros(roleResource);
        super.baseDataStuff4Add(roleResource);
        //设置版本
        roleResource.setVersion(INITIALIZE_VERSION_VALUE);
        return roleResource;
    }

    /***
     * @Description 根据UserId获取他的roleIds
     *
     * @Param
     * @return java.util.List<java.lang.Long>
     * @Date 2022/12/15 20:54
     * @Author hantianbing
     **/
    private List<Long> getRoleIdsByUserId(Long userId){
        List<UserRole> userRoles = userRoleMapper.selectByUserId(userId);
        List<Long> exitRoleIds = new ArrayList<>();
        for (UserRole userRole : userRoles) {
            exitRoleIds.add(userRole.getRoleId());
        }
        return exitRoleIds;
    }

}
